#ifdef TOSSIM                       // large network (~100 nodes)
#define TREEEPOCH_COUNT         205 // number of epochs before committing tree
#define TREEEPOCHUPDATE_COUNT   200 // number of epochs to stop changing parents after
#define DISCOVERY_EPOCHS        600 // minimum number of epochs to use for neighbor discovery
#else                               // small network (~10 nodes)
#define TREEEPOCH_COUNT          55
#define TREEEPOCHUPDATE_COUNT    50
#define DISCOVERY_EPOCHS        120
#endif

#define TREE_COUNT       3        // number of routing trees 

typedef struct {                  // exchange information about parent selection
  uint8_t cmd;                    // command identifier

  uint8_t hops, tree;             // number of hops to root of current tree, and tree number (from 0)
  ADDRESS parent;                 // ID of current parent
  uint32_t phase_start;           // time tree consturction started
} PACKING_MACRO TREECONSTRUCT_MSG;

typedef struct {                  // notify children to start committing the tree, recursively propagated
  uint8_t cmd;
  uint8_t tree;                   // tree number
} PACKING_MACRO TREECOMMIT_MSG;

typedef struct {                  // child sending summary of its subtree
  uint8_t cmd;

  ADDRESS deepest_id, deepestsum_id;  // deepest node in current tree (for routing); deepest in all trees (new root candidate)
  uint8_t deepest_hops, deepesthops_sum, tree; // deepest hops, and tree number
  SUMMARY summary[MAX_SUMMARYDESC];     // send all summaries maintained
} PACKING_MACRO TREESUMMARY_MSG;

typedef struct {
  uint8_t cmd;

  ADDRESS source_node, new_parentnode;
  uint8_t summary_index, is_insert, is_diff, seq_number, tree_index;
  ATTRIBUTE value;  // sent if insert
  SUMMARY summary;  // sent if not insert and not diff
  uint8_t diff_len; uint8_t diff[SUMMARY_LEN]; // sent if not insert and diff
} PACKING_MACRO TREESUMMARYUPDATE_MSG;

typedef struct {                  // propagated down, to notify the root of the new tree
  uint8_t cmd;

  ADDRESS notify_id;              // ID of new root
  uint8_t tree;                   // tree number
} PACKING_MACRO TREEROOTNOTIFY_MSG;

typedef struct {                  // Tree summary structure
  ADDRESS parent;                 // current parent, 0xffff if root
  uint8_t hops;                   // 0 hops if root
  SUMMARY **summary;              // summary for every attribute maintained

  uint8_t uncommitted_children;
  ADDRESS deepest_id, deepestsum_id;   // deepest node in current tree, deepest node in all trees (max sum of levels)
  uint8_t deepest_hops, deepesthops_sum;  // levels of deepest nodes
} PACKING_MACRO TREE_TYPE;

typedef struct {                  // Neighbor summary structure
  uint8_t used;

  ADDRESS id;                     // ID of neighbor
  struct {                        // for each tree
    uint8_t hops;                 // level of that neighbor in the tree
    ADDRESS parent;               // its parent
    uint8_t update_seqnumber;     // sequence number of summary update
    
    SUMMARY **summary;            // summary for all attributes
    uint8_t deepest_hops;         // deepest hops (for routing)
  } PACKING_MACRO trees[TREE_COUNT];
} PACKING_MACRO PEERTREE_TYPE;

TREE_TYPE trees[TREE_COUNT];      // maintains tree information
uint8_t tree_phase;               // value=current tree being built, if value=MAX_TREES then finished

uint8_t peer_discovery;           // true if peer discovery mode is on (prior to tree construction)

uint8_t tree_updated, treemsg_sending; // allow only one tree message sent at a time
uint32_t treeupdate_time, phase_start;
uint8_t tree_busy;    // tree 0 currently selecting parents
uint8_t trees_built;  // trees are functional, cleared by start_treeconstruct, set by command "trees done"

void init_mtree();
void start_treeconstruct();
void init_trees();
void alloc_treesummaries();
void reset_treesummaries();

int list_children(ADDRESS **nodes, uint8_t *node_count, int tree);

void handle_treeconstructmsg(ADDRESS source_id, uint8_t *p);
void handlesent_treeconstructmsg(uint8_t msg_len, uint8_t *p, uint8_t send_success,
  uint8_t node_count, ADDRESS *nodes, uint8_t confirm_seq);
void handle_treecommitmsg(ADDRESS source_id, uint8_t *p);
uint8_t checkaccept_treecommit(ADDRESS source_id, uint8_t *p);
void handle_treesummarymsg(ADDRESS source_id, uint8_t *p);
void handle_treesummaryupdatemsg(ADDRESS source_id, uint8_t *p);
void handle_treerootnotifymsg(ADDRESS source_id, uint8_t *p);
uint8_t checkaccept_treerootnotifymsg(ADDRESS source_id, uint8_t *p);

void init_mobility(ADDRESS *new_parents);
void timer_treeconstruction();

